test(driver-sql): 把 pagination / filter-logic 两条共享矩阵也跑到 driver 轴上 (#4714) - #4735
Merged
Merged
Conversation
… the driver axis (#4714) #4245 (PR #4713) put the D-A3 driver axis under the temporal matrix and left a reusable `live-dialect-matrix.testkit.ts` behind. Two other consumers of the shared `@objectstack/spec/data` matrices in this package were still pinned to one engine: - `sql-driver-pagination-conformance.test.ts` — `client: 'better-sqlite3'` in both describes, over `PAGINATION_CASES` / `PAGINATION_UNORDERED_CASES`; - `sql-driver-or-filter.test.ts` — same client, over `FILTER_LOGIC_CASES`, with the describe named `(SQLite)`. The pagination one is the costly pin. Its own head note says the property half proves nothing on SQLite: twelve rows come back in rowid order every time, so the partition check passes with or without the tie-breaker. That is a local fact about one engine, stated as a permanent excuse — on a real server the property is the half with teeth, which is what objectui#3106 was reported as. Both files now sweep once per cell of `DIALECT_CELLS` over the same cases, asserting the same row-id sets cell for cell. Measured on a live PG 16 @ Asia/Shanghai and MariaDB 10.11 @ +08:00 under TZ=America/New_York: 46 tests per cell, all three cells identical. With `paginationTieBreaker` sabotaged to return null, the live-postgres cell reports 11 distinct ids over a 12-row walk — one row served twice, another never — while every sorted case on SQLite stays green. The cell exists and it bites. - Table names carry the issue prefix (`os4714_*`); the bare `t` / `task` this suite used while SQLite-only would collide with a parallel suite on a shared live database and read as a conformance failure. - `declareUnprovisionedCell` moves into the testkit and the temporal file now calls it too, so one definition of the non-vacuity guard serves all three matrices: missing URL is a named skip, and a red under `OS_EXPECT_LIVE_DIALECT_MATRIX=1` (#4646). - No server-timezone axis here: nothing in these matrices compares an instant, so requiring a non-UTC server would only manufacture reds that say nothing about pagination or `$or`. - The unpaged-unordered read keeps its exact-sequence pin on SQLite only. #4363 promises the driver adds nothing to that shape, not that the server returns a particular order — MySQL hands back InnoDB primary-key order and Postgres its heap order, and pinning either would assert the server's plan as our contract. The contract half (no ORDER BY emitted) is asserted per dialect. - No new CI job: `Temporal Conformance (live PG + MySQL)` already runs the whole package against both servers. `@objectstack/spec/data` is consumed, not edited: no case was softened and no tie-breaker was added to the fixture to keep a dialect green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Br2xsJsczFsTR9bvbh2Ny
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 9 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4714
#4245(PR #4713)把 D-A3 的 driver 轴补到了 temporal 矩阵,并留下
live-dialect-matrix.testkit.ts。本 PR 照抄那个形状,把driver-sql还在消费的另外两条@objectstack/spec/data共享矩阵也搬上同一根轴:sql-driver-pagination-conformance.test.tsPAGINATION_CASES/PAGINATION_UNORDERED_CASESclient: 'better-sqlite3'for (const cell of DIALECT_CELLS)sql-driver-or-filter.test.tsFILTER_LOGIC_CASES(SQLite)结论先说:格子存在,而且真的会咬人 —— 但当前实现是绿的
按 issue 的验收,「红了是交付」。这一轮的实测结果是:三个方言 46 条用例逐格一致,全绿。这不是因为断言被放松了,而是因为
paginationTieBreaker的修复在真服务器上确实成立。为了证明这一格不是空转,我做了一次破坏性实验(临时把paginationTieBreaker改成对 managed 表也返回null,测完已git checkout还原,未进入本 PR 的 diff):sqlitelive postgresvisits every row exactly once报expected 11 to be 12(一行被翻了两次、另一行一次都没出现),orders pages consistently红 4 条live mysqlPG 上那句
expected 11 to be 12就是 objectui#3106 的原始故障,一字不差 —— 这正是文件头注自己说 SQLite 上证不出来的那半边。换句话说:在补上这根轴之前,删掉分页修复只会让 emitted-SQL 那半边红;性质断言在唯一跑得到的方言上是恒真的。破坏实验的 PG 证据:
(
r06整趟走丢,r12出现两次。)实测环境与逐格证据
本地起了真服务器,配置与 CI 的
Temporal Conformance (live PG + MySQL)job 对齐:PostgreSQL 16.13 @Asia/Shanghai、MariaDB 10.11.14 @+08:00,进程TZ=America/New_York,并开OS_EXPECT_LIVE_DIALECT_MATRIX=1。三格用例数完全相同(46 × 3 = 138),行 id 集合逐格一致。整包(CI 形状,含 temporal 矩阵与全部 live 套件):
说明:MariaDB 10.11 不等于 CI 的 MySQL 8.0(容器里没有 docker daemon,只能用系统自带的 server)。仓库注释里说 #3942 的手工验证正是跑在 MariaDB 10.11 上,两者互为补充;MySQL 8.0 那一格由 CI 上这个 job 给出。
非空转守卫(没有退化)
缺 URL → 具名 skip,不是静默跳过:
OS_EXPECT_LIVE_DIALECT_MATRIX=1且缺 URL → 直接红(实测 4 条):这个守卫从 temporal 文件里上提到了 testkit(
declareUnprovisionedCell(cell, matrix)),三条矩阵共用一份定义 —— 复制三份的守卫可以在其中一份里悄悄变弱,而「巡检发现零个 cell 却报 OK」正是 #4646 已经付过一次学费的形状。temporal 文件的调用点同步改掉,行为与文案逐字不变。几处刻意的判断(请重点看这三条)
$or里没有任何一个 instant 参与比较,硬要求非 UTC 服务器只会制造出与本矩阵无关的红。",SQLite/MySQL`)构造断言 —— 于是「ORDER BY 真的到达了数据库」这句话在三个真引擎上分别成立,而不只是在 knex 的 SQLite 编译结果上。诚实的边界:12 行只是一次 seq scan,真服务器也可能恰好稳定返回(本轮 MySQL 就是这样)。所以 emitted-SQL 那一半仍然是必要的,两半互相兜底 —— 头注里写清楚了。
约束遵守情况
packages/plugins/driver-sql/**;@objectstack/spec/data只消费不修改 —— 没有为了变绿给 fixture 加 tiebreaker、改用例或放宽断言。packages/spec/**零改动;content/docs/releases/未碰;无新增 CI job(现有 job 已经在跑整包)。os4714_pagination/os4714_pagination_clause/os4714_filter_logic/os4714_filter_logic_windows),替换掉原来裸的t/task—— 共享 live 库上裸表名会和并行套件抢,抢输的那边会表现为一次假的 conformance 失败。一处脚手架 bug(自己的,已修)
从
beforeEach(每条用例一个:memory:driver)改成beforeAll(live cell 承担不起每条断言一个连接)之后,nondeterministicPagingWarned这个「每个 object 只警告一次」的账本开始跨用例共享,导致says so, once, ...数到 0 次。修法是给那条用例自己的 object 名,而不是去清账本 —— 属于 issue 里说的「红的是脚手架自身,那是你的 bug」。关联
#4245 / PR #4713(driver 轴 + server-timezone 轴,temporal 矩阵)、#4081、#4363、objectui#3106、#3774、#4646;ADR-0053 D-A3。
🤖 Generated with Claude Code
https://claude.ai/code/session_015Br2xsJsczFsTR9bvbh2Ny
Generated by Claude Code